package inpututil

import "strings"

// A Key represents a keyboard key.
// These keys represent pysical keys of US keyboard.
// For example, KeyQ represents Q key on US keyboards and ' (quote) key on Dvorak keyboards.
type Key int

// Keys, 只有整数支持.
const (
	KeyA              Key = iota
	KeyB
	KeyC
	KeyD
	KeyE
	KeyF
	KeyG
	KeyH
	KeyI
	KeyJ
	KeyK
	KeyL
	KeyM
	KeyN
	KeyO
	KeyP
	KeyQ
	KeyR
	KeyS
	KeyT
	KeyU
	KeyV
	KeyW
	KeyX
	KeyY
	KeyZ
	KeyAltLeft
	KeyAltRight
	KeyArrowDown
	KeyArrowLeft
	KeyArrowRight
	KeyArrowUp
	KeyBackquote
	KeyBackslash
	KeyBackspace
	KeyBracketLeft
	KeyBracketRight
	KeyCapsLock
	KeyComma
	KeyContextMenu
	KeyControlLeft
	KeyControlRight
	KeyDelete
	KeyDigit0
	KeyDigit1
	KeyDigit2
	KeyDigit3
	KeyDigit4
	KeyDigit5
	KeyDigit6
	KeyDigit7
	KeyDigit8
	KeyDigit9
	KeyEnd
	KeyEnter
	KeyEqual
	KeyEscape
	KeyF1
	KeyF2
	KeyF3
	KeyF4
	KeyF5
	KeyF6
	KeyF7
	KeyF8
	KeyF9
	KeyF10
	KeyF11
	KeyF12
	KeyHome
	KeyInsert
	KeyMetaLeft
	KeyMetaRight
	KeyMinus
	KeyNumLock
	KeyNumpad0
	KeyNumpad1
	KeyNumpad2
	KeyNumpad3
	KeyNumpad4
	KeyNumpad5
	KeyNumpad6
	KeyNumpad7
	KeyNumpad8
	KeyNumpad9
	KeyNumpadAdd
	KeyNumpadDecimal
	KeyNumpadDivide
	KeyNumpadEnter
	KeyNumpadEqual
	KeyNumpadMultiply
	KeyNumpadSubtract
	KeyPageDown
	KeyPageUp
	KeyPause
	KeyPeriod
	KeyPrintScreen
	KeyQuote
	KeyScrollLock
	KeySemicolon
	KeyShiftLeft
	KeyShiftRight
	KeySlash
	KeySpace
	KeyTab
	KeyAlt
	KeyControl
	KeyShift
	KeyMeta
	KeyMax            Key = KeyMeta

	// Keys for backward compatibility.
	// Deprecated: as of v2.1.
)

func (k Key) isValid() bool {
	switch k {
	case KeyA:
		return true
	case KeyB:
		return true
	case KeyC:
		return true
	case KeyD:
		return true
	case KeyE:
		return true
	case KeyF:
		return true
	case KeyG:
		return true
	case KeyH:
		return true
	case KeyI:
		return true
	case KeyJ:
		return true
	case KeyK:
		return true
	case KeyL:
		return true
	case KeyM:
		return true
	case KeyN:
		return true
	case KeyO:
		return true
	case KeyP:
		return true
	case KeyQ:
		return true
	case KeyR:
		return true
	case KeyS:
		return true
	case KeyT:
		return true
	case KeyU:
		return true
	case KeyV:
		return true
	case KeyW:
		return true
	case KeyX:
		return true
	case KeyY:
		return true
	case KeyZ:
		return true
	case KeyAlt:
		return true
	case KeyAltLeft:
		return true
	case KeyAltRight:
		return true
	case KeyArrowDown:
		return true
	case KeyArrowLeft:
		return true
	case KeyArrowRight:
		return true
	case KeyArrowUp:
		return true
	case KeyBackquote:
		return true
	case KeyBackslash:
		return true
	case KeyBackspace:
		return true
	case KeyBracketLeft:
		return true
	case KeyBracketRight:
		return true
	case KeyCapsLock:
		return true
	case KeyComma:
		return true
	case KeyContextMenu:
		return true
	case KeyControl:
		return true
	case KeyControlLeft:
		return true
	case KeyControlRight:
		return true
	case KeyDelete:
		return true
	case KeyDigit0:
		return true
	case KeyDigit1:
		return true
	case KeyDigit2:
		return true
	case KeyDigit3:
		return true
	case KeyDigit4:
		return true
	case KeyDigit5:
		return true
	case KeyDigit6:
		return true
	case KeyDigit7:
		return true
	case KeyDigit8:
		return true
	case KeyDigit9:
		return true
	case KeyEnd:
		return true
	case KeyEnter:
		return true
	case KeyEqual:
		return true
	case KeyEscape:
		return true
	case KeyF1:
		return true
	case KeyF2:
		return true
	case KeyF3:
		return true
	case KeyF4:
		return true
	case KeyF5:
		return true
	case KeyF6:
		return true
	case KeyF7:
		return true
	case KeyF8:
		return true
	case KeyF9:
		return true
	case KeyF10:
		return true
	case KeyF11:
		return true
	case KeyF12:
		return true
	case KeyHome:
		return true
	case KeyInsert:
		return true
	case KeyMeta:
		return true
	case KeyMetaLeft:
		return true
	case KeyMetaRight:
		return true
	case KeyMinus:
		return true
	case KeyNumLock:
		return true
	case KeyNumpad0:
		return true
	case KeyNumpad1:
		return true
	case KeyNumpad2:
		return true
	case KeyNumpad3:
		return true
	case KeyNumpad4:
		return true
	case KeyNumpad5:
		return true
	case KeyNumpad6:
		return true
	case KeyNumpad7:
		return true
	case KeyNumpad8:
		return true
	case KeyNumpad9:
		return true
	case KeyNumpadAdd:
		return true
	case KeyNumpadDecimal:
		return true
	case KeyNumpadDivide:
		return true
	case KeyNumpadEnter:
		return true
	case KeyNumpadEqual:
		return true
	case KeyNumpadMultiply:
		return true
	case KeyNumpadSubtract:
		return true
	case KeyPageDown:
		return true
	case KeyPageUp:
		return true
	case KeyPause:
		return true
	case KeyPeriod:
		return true
	case KeyPrintScreen:
		return true
	case KeyQuote:
		return true
	case KeyScrollLock:
		return true
	case KeySemicolon:
		return true
	case KeyShift:
		return true
	case KeyShiftLeft:
		return true
	case KeyShiftRight:
		return true
	case KeySlash:
		return true
	case KeySpace:
		return true
	case KeyTab:
		return true

	default:
		return false
	}
}

// String returns a string representing the key.
//
// If k is an undefined key, String returns an empty string.
func (k Key) String() string {
	switch k {
	case KeyA:
		return "A"
	case KeyB:
		return "B"
	case KeyC:
		return "C"
	case KeyD:
		return "D"
	case KeyE:
		return "E"
	case KeyF:
		return "F"
	case KeyG:
		return "G"
	case KeyH:
		return "H"
	case KeyI:
		return "I"
	case KeyJ:
		return "J"
	case KeyK:
		return "K"
	case KeyL:
		return "L"
	case KeyM:
		return "M"
	case KeyN:
		return "N"
	case KeyO:
		return "O"
	case KeyP:
		return "P"
	case KeyQ:
		return "Q"
	case KeyR:
		return "R"
	case KeyS:
		return "S"
	case KeyT:
		return "T"
	case KeyU:
		return "U"
	case KeyV:
		return "V"
	case KeyW:
		return "W"
	case KeyX:
		return "X"
	case KeyY:
		return "Y"
	case KeyZ:
		return "Z"
	case KeyAlt:
		return "Alt"
	case KeyAltLeft:
		return "AltLeft"
	case KeyAltRight:
		return "AltRight"
	case KeyArrowDown:
		return "ArrowDown"
	case KeyArrowLeft:
		return "ArrowLeft"
	case KeyArrowRight:
		return "ArrowRight"
	case KeyArrowUp:
		return "ArrowUp"
	case KeyBackquote:
		return "Backquote"
	case KeyBackslash:
		return "Backslash"
	case KeyBackspace:
		return "Backspace"
	case KeyBracketLeft:
		return "BracketLeft"
	case KeyBracketRight:
		return "BracketRight"
	case KeyCapsLock:
		return "CapsLock"
	case KeyComma:
		return "Comma"
	case KeyContextMenu:
		return "ContextMenu"
	case KeyControl:
		return "Control"
	case KeyControlLeft:
		return "ControlLeft"
	case KeyControlRight:
		return "ControlRight"
	case KeyDelete:
		return "Delete"
	case KeyDigit0:
		return "Digit0"
	case KeyDigit1:
		return "Digit1"
	case KeyDigit2:
		return "Digit2"
	case KeyDigit3:
		return "Digit3"
	case KeyDigit4:
		return "Digit4"
	case KeyDigit5:
		return "Digit5"
	case KeyDigit6:
		return "Digit6"
	case KeyDigit7:
		return "Digit7"
	case KeyDigit8:
		return "Digit8"
	case KeyDigit9:
		return "Digit9"
	case KeyEnd:
		return "End"
	case KeyEnter:
		return "Enter"
	case KeyEqual:
		return "Equal"
	case KeyEscape:
		return "Escape"
	case KeyF1:
		return "F1"
	case KeyF2:
		return "F2"
	case KeyF3:
		return "F3"
	case KeyF4:
		return "F4"
	case KeyF5:
		return "F5"
	case KeyF6:
		return "F6"
	case KeyF7:
		return "F7"
	case KeyF8:
		return "F8"
	case KeyF9:
		return "F9"
	case KeyF10:
		return "F10"
	case KeyF11:
		return "F11"
	case KeyF12:
		return "F12"
	case KeyHome:
		return "Home"
	case KeyInsert:
		return "Insert"
	case KeyMeta:
		return "Meta"
	case KeyMetaLeft:
		return "MetaLeft"
	case KeyMetaRight:
		return "MetaRight"
	case KeyMinus:
		return "Minus"
	case KeyNumLock:
		return "NumLock"
	case KeyNumpad0:
		return "Numpad0"
	case KeyNumpad1:
		return "Numpad1"
	case KeyNumpad2:
		return "Numpad2"
	case KeyNumpad3:
		return "Numpad3"
	case KeyNumpad4:
		return "Numpad4"
	case KeyNumpad5:
		return "Numpad5"
	case KeyNumpad6:
		return "Numpad6"
	case KeyNumpad7:
		return "Numpad7"
	case KeyNumpad8:
		return "Numpad8"
	case KeyNumpad9:
		return "Numpad9"
	case KeyNumpadAdd:
		return "NumpadAdd"
	case KeyNumpadDecimal:
		return "NumpadDecimal"
	case KeyNumpadDivide:
		return "NumpadDivide"
	case KeyNumpadEnter:
		return "NumpadEnter"
	case KeyNumpadEqual:
		return "NumpadEqual"
	case KeyNumpadMultiply:
		return "NumpadMultiply"
	case KeyNumpadSubtract:
		return "NumpadSubtract"
	case KeyPageDown:
		return "PageDown"
	case KeyPageUp:
		return "PageUp"
	case KeyPause:
		return "Pause"
	case KeyPeriod:
		return "Period"
	case KeyPrintScreen:
		return "PrintScreen"
	case KeyQuote:
		return "Quote"
	case KeyScrollLock:
		return "ScrollLock"
	case KeySemicolon:
		return "Semicolon"
	case KeyShift:
		return "Shift"
	case KeyShiftLeft:
		return "ShiftLeft"
	case KeyShiftRight:
		return "ShiftRight"
	case KeySlash:
		return "Slash"
	case KeySpace:
		return "Space"
	case KeyTab:
		return "Tab"
	}
	return ""
}

func keyNameToKeyCode(name string) (Key, bool) {
	switch strings.ToLower(name) {
	case "0":
		return KeyDigit0, true
	case "1":
		return KeyDigit1, true
	case "2":
		return KeyDigit2, true
	case "3":
		return KeyDigit3, true
	case "4":
		return KeyDigit4, true
	case "5":
		return KeyDigit5, true
	case "6":
		return KeyDigit6, true
	case "7":
		return KeyDigit7, true
	case "8":
		return KeyDigit8, true
	case "9":
		return KeyDigit9, true
	case "a":
		return KeyA, true
	case "b":
		return KeyB, true
	case "c":
		return KeyC, true
	case "d":
		return KeyD, true
	case "e":
		return KeyE, true
	case "f":
		return KeyF, true
	case "g":
		return KeyG, true
	case "h":
		return KeyH, true
	case "i":
		return KeyI, true
	case "j":
		return KeyJ, true
	case "k":
		return KeyK, true
	case "l":
		return KeyL, true
	case "m":
		return KeyM, true
	case "n":
		return KeyN, true
	case "o":
		return KeyO, true
	case "p":
		return KeyP, true
	case "q":
		return KeyQ, true
	case "r":
		return KeyR, true
	case "s":
		return KeyS, true
	case "t":
		return KeyT, true
	case "u":
		return KeyU, true
	case "v":
		return KeyV, true
	case "w":
		return KeyW, true
	case "x":
		return KeyX, true
	case "y":
		return KeyY, true
	case "z":
		return KeyZ, true
	case "alt":
		return KeyAlt, true
	case "altleft":
		return KeyAltLeft, true
	case "altright":
		return KeyAltRight, true
	case "arrowdown":
		return KeyArrowDown, true
	case "arrowleft":
		return KeyArrowLeft, true
	case "arrowright":
		return KeyArrowRight, true
	case "arrowup":
		return KeyArrowUp, true
	case "backquote":
		return KeyBackquote, true
	case "backslash":
		return KeyBackslash, true
	case "backspace":
		return KeyBackspace, true
	case "bracketleft":
		return KeyBracketLeft, true
	case "bracketright":
		return KeyBracketRight, true
	case "capslock":
		return KeyCapsLock, true
	case "comma":
		return KeyComma, true
	case "contextmenu":
		return KeyContextMenu, true
	case "control":
		return KeyControl, true
	case "controlleft":
		return KeyControlLeft, true
	case "controlright":
		return KeyControlRight, true
	case "delete":
		return KeyDelete, true
	case "digit0":
		return KeyDigit0, true
	case "digit1":
		return KeyDigit1, true
	case "digit2":
		return KeyDigit2, true
	case "digit3":
		return KeyDigit3, true
	case "digit4":
		return KeyDigit4, true
	case "digit5":
		return KeyDigit5, true
	case "digit6":
		return KeyDigit6, true
	case "digit7":
		return KeyDigit7, true
	case "digit8":
		return KeyDigit8, true
	case "digit9":
		return KeyDigit9, true
	case "end":
		return KeyEnd, true
	case "enter":
		return KeyEnter, true
	case "equal":
		return KeyEqual, true
	case "escape":
		return KeyEscape, true
	case "f1":
		return KeyF1, true
	case "f2":
		return KeyF2, true
	case "f3":
		return KeyF3, true
	case "f4":
		return KeyF4, true
	case "f5":
		return KeyF5, true
	case "f6":
		return KeyF6, true
	case "f7":
		return KeyF7, true
	case "f8":
		return KeyF8, true
	case "f9":
		return KeyF9, true
	case "f10":
		return KeyF10, true
	case "f11":
		return KeyF11, true
	case "f12":
		return KeyF12, true
	case "meta":
		return KeyMeta, true
	case "metaleft":
		return KeyMetaLeft, true
	case "metaright":
		return KeyMetaRight, true
	case "minus":
		return KeyMinus, true
	case "numlock":
		return KeyNumLock, true
	case "numpad0":
		return KeyNumpad0, true
	case "numpad1":
		return KeyNumpad1, true
	case "numpad2":
		return KeyNumpad2, true
	case "numpad3":
		return KeyNumpad3, true
	case "numpad4":
		return KeyNumpad4, true
	case "numpad5":
		return KeyNumpad5, true
	case "numpad6":
		return KeyNumpad6, true
	case "numpad7":
		return KeyNumpad7, true
	case "numpad8":
		return KeyNumpad8, true
	case "numpad9":
		return KeyNumpad9, true
	case "numpadadd":
		return KeyNumpadAdd, true
	case "numpaddecimal":
		return KeyNumpadDecimal, true
	case "numpaddivide":
		return KeyNumpadDivide, true
	case "numpadenter":
		return KeyNumpadEnter, true
	case "numpadequal":
		return KeyNumpadEqual, true
	case "numpadmultiply":
		return KeyNumpadMultiply, true
	case "numpadsubtract":
		return KeyNumpadSubtract, true
	case "pagedown":
		return KeyPageDown, true
	case "pageup":
		return KeyPageUp, true
	case "pause":
		return KeyPause, true
	case "period":
		return KeyPeriod, true
	case "printscreen":
		return KeyPrintScreen, true
	case "quote":
		return KeyQuote, true
	case "scrolllock":
		return KeyScrollLock, true
	case "semicolon":
		return KeySemicolon, true
	case "shift":
		return KeyShift, true
	case "shiftleft":
		return KeyShiftLeft, true
	case "shiftright":
		return KeyShiftRight, true
	case "slash":
		return KeySlash, true
	case "space":
		return KeySpace, true
	case "tab":
		return KeyTab, true
	}
	return 0, false
}


